import io
import json
import re
from contextlib import redirect_stdout
from pathlib import Path
from tempfile import TemporaryDirectory

import typer
from datamodel_code_generator.__main__ import main as codegen

import e621
from e621.api import E621

app = typer.Typer(add_completion=False)
MODELS_FILE = Path(e621.__file__).parent / "autogenerated_models.py"
API_ENDPOINTS = (
    "posts",
    "post_flags",
    "tags",
    "tag_aliases",
    "notes",
    "pools",
    "users",
    "post_versions",
    "post_approvals",
    "note_versions",
    "wiki_pages",
    "wiki_page_versions",
    "artists",
    "artist_versions",
    "tag_type_versions",
    "tag_implications",
    "bulk_update_requests",
    "blips",
    "takedowns",
    "user_feedbacks",
    "forum_topics",
    "forum_posts",
    "post_sets",
    # "post_disapprovals", # Returns 404
    # "comments", # Equivalent to posts but shouldn't be
    # "favorites",  # Equivalent to posts
)
# The ^ and MULTILINE here are needed because we don't want to match inner classes
RE_CLASSNAME = re.compile(r"^class (\w+)\(", flags=re.MULTILINE)


all_jsons = {}


@app.command()
def main(
    username: str = typer.Option(..., prompt=True),
    api_key: str = typer.Option(..., prompt=True),
):
    e6api = E621((username, api_key), timeout=20)
    with TemporaryDirectory("e621-model-generator") as tempdir:
        tempdir = Path(tempdir)
        for endpoint in API_ENDPOINTS:
            json_template = e6api.session.get(endpoint, params={"limit": 500}).json()
            all_jsons[endpoint] = json_template
        final_json = (tempdir / "models").with_suffix(".json")
        final_json.write_text(json.dumps(all_jsons, ensure_ascii=False))
        print("Generating")
        with io.StringIO() as temp_stdout, redirect_stdout(temp_stdout):
            codegen(
                [
                    "--input",
                    str(final_json),
                    "--input-file-type",
                    "json",
                    "--base-class",
                    "e621.models.BaseModel",
                    "--reuse-model",
                    "--class-name",
                    "AllJsonsTempVar",
                ]
            )
            stdout = temp_stdout.getvalue()
        print("Normalizing")

    models_source = stdout.replace("TagAliase", "TagAlias")
    model_class_names = [repr(n) for n in RE_CLASSNAME.findall(models_source)]
    all_list = f"__all__ = {', '.join(model_class_names)}\n\n\n"
    models_source += all_list
    MODELS_FILE.write_text(models_source)


if __name__ == "__main__":
    app()
